package com.onstar.cn.framework.utils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.support.v4.app.Fragment;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

import com.onstar.cn.common.log.LogManager;
import com.onstar.cn.common.util.AppRUtils;
import com.onstar.cn.framework.annotation.ContentView;
import com.onstar.cn.framework.annotation.EventBase;
import com.onstar.cn.framework.annotation.FindViewById;
import com.onstar.cn.framework.base.ViewFinder;

/**
 * View 注入工具类
 * 
 * @author 7828wc
 * 
 */
public class ViewInjectUtils {
	private static LogManager log = LogManager.getInstance();

	/**
	 * 设置Activity的setContentView
	 * 
	 * @param activity
	 */
	private static void injectContentView(Activity activity) {
		Class<? extends Activity> clazz = activity.getClass();
		// 查询类上是否存在ContentView注解
		ContentView contentView = clazz.getAnnotation(ContentView.class);
		if (contentView != null)// 存在
		{
			int contentViewLayoutId = contentView.value();
			try {
				Method method = clazz.getMethod(Constants.METHOD_SET_CONTENTVIEW, int.class);
				method.setAccessible(true);
				method.invoke(activity, contentViewLayoutId);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 遍历所有的成员变量，得到FindViewById注解，反射进行设置this.findViewById();
	 * 
	 * @param activity
	 */
	private static void injectViews(Activity activity) {
		Class<? extends Activity> clazz = activity.getClass();
		injectViewsByObject(clazz, activity);
		// Field[] fields = clazz.getDeclaredFields();
		// // 遍历所有成员变量
		// for (Field field : fields) {
		// FindViewById viewInjectAnnotation =
		// field.getAnnotation(FindViewById.class);
		// if (viewInjectAnnotation != null) {
		// int viewId = viewInjectAnnotation.value();
		// // 初始化View
		// if (viewId == -1) {
		// viewId = AppRUtils.getInstance(activity).getResouceId("id",
		// field.getName());
		// }
		// try {
		// Method method = clazz.getMethod(Constants.METHOD_FIND_VIEW_BY_ID,
		// int.class);
		// Object resView = method.invoke(activity, viewId);
		// field.setAccessible(true);
		// field.set(activity, resView);
		// } catch (Exception e) {
		// e.printStackTrace();
		// }
		//
		// int background = viewInjectAnnotation.background();
		// String methodName = "";
		// if (background != -1) {
		// if (ImageView.class.isAssignableFrom(field.getType())) {
		// methodName = Constants.METHOD_IMAGE_RESOURCE;
		// } else if (Button.class.isAssignableFrom(field.getType())) {
		// methodName = Constants.METHOD_BACKGROUND;
		// } else {
		// methodName = Constants.METHOD_BACKGROUND_RESOURCE;
		// }
		// View childView = activity.findViewById(viewId);
		// log.d("view:" + childView);
		// try {
		// if (Button.class.isAssignableFrom(field.getType())) {
		// Method setEventListenerMethod = Button.class.getMethod(methodName,
		// Drawable.class);
		// setEventListenerMethod.invoke(childView,
		// activity.getDrawable(background));
		// } else if (ImageView.class.isAssignableFrom(field.getType())) {
		// Method setEventListenerMethod = ImageView.class.getMethod(methodName,
		// int.class);
		// setEventListenerMethod.invoke(childView, background);
		// }else {
		// Method setEventListenerMethod = View.class.getMethod(methodName,
		// int.class);
		// setEventListenerMethod.invoke(childView, background);
		// }
		// } catch (Exception e) {
		// e.printStackTrace();
		// } catch (java.lang.OutOfMemoryError e1) {
		// e1.printStackTrace();
		// childView = null;
		// }
		// }
		// }
		// }
	}

	public static boolean injectViewsByViewFinder(Class<?> clazz, Object objClass, Context context,
			ViewFinder viewFinder) {
		boolean isResult = false;
		Field[] fields = clazz.getDeclaredFields();
		// 遍历所有成员变量
		for (Field field : fields) {
			FindViewById viewInjectAnnotation = field.getAnnotation(FindViewById.class);
			if (viewInjectAnnotation != null) {
				int viewId = viewInjectAnnotation.value();
				// 初始化View
				try{
					if (viewId == -1) {
						viewId = AppRUtils.getInstance(context).getResouceId("id", field.getName());
						log.i("field.getName() --->" + field.getName());
					}
				}catch(Exception e) {
					log.e(e.getMessage() + "field.getName() == " + field.getName());
				}

				try {
					if (viewFinder != null) {
						Method method = viewFinder.getClass().getMethod(Constants.METHOD_FIND_VIEW_BY_ID, int.class);
						Object resView = method.invoke(viewFinder, viewId);
						field.setAccessible(true);
						field.set(objClass, resView);
						isResult = true;
					} else {
						Method method = clazz.getMethod(Constants.METHOD_FIND_VIEW_BY_ID, int.class);
						Object resView = method.invoke(context, viewId);
						field.setAccessible(true);
						field.set(context, resView);
						isResult = true;
					}
				} catch (Exception e) {
					e.printStackTrace();
					isResult = false;
				}

				int background = viewInjectAnnotation.background();
				String methodName = "";
				if (background != -1) {
					if (ImageView.class.isAssignableFrom(field.getType())) {
						methodName = Constants.METHOD_IMAGE_RESOURCE;
					} else if (Button.class.isAssignableFrom(field.getType())) {
						methodName = Constants.METHOD_BACKGROUND;
					} else {
						methodName = Constants.METHOD_BACKGROUND_RESOURCE;
					}
					View childView;
					if(viewFinder == null) {
						childView = ((Activity)context).findViewById(viewId);
					}else {
						childView = viewFinder.findViewById(viewId);
					}
					try {
						if (Button.class.isAssignableFrom(field.getType())) {
							Method setEventListenerMethod = Button.class.getMethod(methodName, Drawable.class);
							//setEventListenerMethod.invoke(childView, background);
							setEventListenerMethod.invoke(childView, context.getResources().getDrawable(background));

						} else if (ImageView.class.isAssignableFrom(field.getType())) {
							Method setEventListenerMethod = ImageView.class.getMethod(methodName, int.class);
							setEventListenerMethod.invoke(childView, background);
						} else {
							Method setEventListenerMethod = View.class.getMethod(methodName, int.class);
							setEventListenerMethod.invoke(childView, background);
						}
						isResult = true;
					} catch (Exception e) {
						log.e(e.getMessage());
						e.printStackTrace();
						isResult = false;
					} catch (java.lang.OutOfMemoryError e1) {
						e1.printStackTrace();
						isResult = false;
						childView = null;
					}
				}
			}
		}
		return isResult;
	}

	public static boolean injectViews(Class<?> clazz, Object objcect, View view) {
		return injectViewsByViewFinder(clazz, objcect, view.getContext(), new ViewFinder(view));
	}

	public static boolean injectViewsByObject(Class<?> clazz, Context context) {
		return injectViewsByViewFinder(clazz, null, context, null);
	}

	/**
	 * 遍历所有的成员变量，得到FindViewById注解，反射进行设置this.findViewById();
	 * 
	 * @param activity
	 */
	private static void injectViews(Fragment fragment, View view) {
		// View view = fragment.getView();
		Class<? extends Fragment> clazz = fragment.getClass();
		injectViews(clazz, fragment, view);
	}

	/**
	 * 遍历所有的方法，拿到该方法省的OnClick注解，然后再拿到该注解上的EventBase注解，得到事件监听的需要调用的方法名，类型，
	 * 和需要调用的方法的名称；通过Proxy和InvocationHandler得到监听器的代理对象，显示设置了方法，最后通过反射设置监听器
	 * 
	 * @param activity
	 */
	private static void injectEvents(Activity activity) {
		Class<? extends Activity> clazz = activity.getClass();
		Method[] methods = clazz.getMethods();
		// 遍历所有的方法
		for (Method method : methods) {
			Annotation[] annotations = method.getAnnotations();
			// 拿到方法上的所有的注解
			for (Annotation annotation : annotations) {
				Class<? extends Annotation> annotationType = annotation.annotationType();
				if (annotation == annotationType.getAnnotation(Override.class)
						|| annotation == annotationType.getAnnotation(SuppressWarnings.class)) {
					continue;
				}
				// 拿到注解上的注解
				EventBase eventBaseAnnotation = annotationType.getAnnotation(EventBase.class);
				// 如果设置为EventBase
				if (eventBaseAnnotation != null) {
					// 取出设置监听器的名称，监听器的类型，调用的方法名
					String listenerSetter = eventBaseAnnotation.listenerSetter();
					Class<?> listenerType = eventBaseAnnotation.listenerType();
					String methodName = eventBaseAnnotation.methodName();
					try {
						// 拿到OnClick注解中的value方法
						Method aMethod = annotationType.getDeclaredMethod("value");
						// 取出所有的viewId
						int[] viewIds = (int[]) aMethod.invoke(annotation);
						// 通过InvocationHandler设置代理
						DynamicHandler handler = new DynamicHandler(activity);
						handler.addMethod(methodName, method);
						Object listener = Proxy.newProxyInstance(listenerType.getClassLoader(),
								new Class<?>[] { listenerType }, handler);
						// 遍历所有的View，设置事件
						for (int viewId : viewIds) {
							View view = activity.findViewById(viewId);
							Method setEventListenerMethod = View.class.getMethod(listenerSetter, listenerType);
							LogManager.getInstance().d("inject event view id:"+viewId);
							setEventListenerMethod.invoke(view, listener);
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
				}

			}
		}
	}

	/**
	 * 遍历所有的方法，拿到该方法省的OnClick注解，然后再拿到该注解上的EventBase注解，得到事件监听的需要调用的方法名，类型，
	 * 和需要调用的方法的名称；通过Proxy和InvocationHandler得到监听器的代理对象，显示设置了方法，最后通过反射设置监听器
	 * 
	 * @param activity
	 */
	private static void injectEventsByFragment(Fragment fragment, View view) {
		Class<? extends Fragment> clazz = fragment.getClass();
		Method[] methods = clazz.getMethods();
		// 遍历所有的方法
		for (Method method : methods) {
			Annotation[] annotations = method.getAnnotations();
			// 拿到方法上的所有的注解
			for (Annotation annotation : annotations) {
				Class<? extends Annotation> annotationType = annotation.annotationType();
				if (annotation == annotationType.getAnnotation(Override.class)
						|| annotation == annotationType.getAnnotation(SuppressWarnings.class)) {
					continue;
				}
				// 拿到注解上的注解
				EventBase eventBaseAnnotation = annotationType.getAnnotation(EventBase.class);
				// 如果设置为EventBase
				if (eventBaseAnnotation != null) {
					// 取出设置监听器的名称，监听器的类型，调用的方法名
					String listenerSetter = eventBaseAnnotation.listenerSetter();
					Class<?> listenerType = eventBaseAnnotation.listenerType();
					String methodName = eventBaseAnnotation.methodName();
					try {
						// 拿到OnClick注解中的value方法
						Method aMethod = annotationType.getDeclaredMethod("value");
						// 取出所有的viewId
						int[] viewIds = (int[]) aMethod.invoke(annotation);
						// 通过InvocationHandler设置代理
						DynamicHandler handler = new DynamicHandler(fragment);
						handler.addMethod(methodName, method);
						Object listener = Proxy.newProxyInstance(listenerType.getClassLoader(),
								new Class<?>[] { listenerType }, handler);
						// 遍历所有的View，设置事件
						for (int viewId : viewIds) {
							View childView = view.findViewById(viewId);
							Method setEventListenerMethod = childView.getClass()
									.getMethod(listenerSetter, listenerType);
							setEventListenerMethod.invoke(childView, listener);
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
				}

			}
		}
	}

	public static void inject(Activity activity) {
		injectContentView(activity);
		injectViews(activity);
		injectEvents(activity);
	}

	public static void injectByFragment(Fragment fragment, View view) {
		injectViews(fragment, view);
		injectEventsByFragment(fragment, view);
	}
}
